package com.itlong.cloud.controller.pad;

import com.alibaba.fastjson.JSON;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.Callback;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.esotericsoftware.minlog.Log;
import com.itlong.cloud.POJO.DTO.app.AppUploadPassRecordDTO;
import com.itlong.cloud.POJO.DTO.operate.OperateDeviceAuthFileDTO;
import com.itlong.cloud.POJO.DTO.operate.OperateDeviceWhiteListAuthFileConsumeRecordsDTO;
import com.itlong.cloud.POJO.DTO.operate.OperateDeviceWhiteListAuthRulesDTO;
import com.itlong.cloud.POJO.DTO.operate.OperateDeviceWhiteListDTO;
import com.itlong.cloud.POJO.DTO.property.PropertyDeviceCloudControllerGetDTO;
import com.itlong.cloud.POJO.DTO.sdk.jd.JDPassRecordDTO;
import com.itlong.cloud.POJO.PO.DeviceRunLogPO;
import com.itlong.cloud.POJO.PO.ProjectPO;
import com.itlong.cloud.POJO.PO.SpecialDevicePadInfoPO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.app.*;
import com.itlong.cloud.POJO.VO.operate.*;
import com.itlong.cloud.POJO.VO.property.CloudDeviceUpdateInfoVO;
import com.itlong.cloud.POJO.VO.property.CloudElevatorVO;
import com.itlong.cloud.POJO.VO.property.PropertyDeviceCloudControllerEleVO;
import com.itlong.cloud.POJO.VO.property.PropertyDeviceCloudControllerGetVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.annotation.UnAuthAccessRequired;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.enumerate.ecode.AppErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.ErrorCode;
import com.itlong.cloud.enumerate.ecode_en.AppErrorCodeEnumEN;
import com.itlong.cloud.enumerate.ecode_en.BaseErrorCodeEnumEN;
import com.itlong.cloud.equip.app.IAppDeviceServiceClient;
import com.itlong.cloud.equip.commons.ICloudDeviceBaseServiceClient;
import com.itlong.cloud.equip.operate.IOperateDeviceWhiteListAuthFileConsumeRecordsServiceClient;
import com.itlong.cloud.equip.operate.IOperateDeviceWhiteListAuthFileServiceClient;
import com.itlong.cloud.equip.operate.IOperateDeviceWhiteListAuthRulesServiceClient;
import com.itlong.cloud.equip.operate.IOperateDeviceWhiteListServiceClient;
import com.itlong.cloud.equip.property.ICloudIntercomServiceClient;
import com.itlong.cloud.equip.property.IDeviceCloudControllerServiceClient;
import com.itlong.cloud.equip.property.IPadFaceSyncDataServiceClient;
import com.itlong.cloud.equip.property.IPropertyEquipServiceClient;
import com.itlong.cloud.equip.sdk.ICloudElevatorSDKServerCloudServiceClient;
import com.itlong.cloud.iottp.IIotDeviceOnlineServiceClient;
import com.itlong.cloud.project.operate.IOperateFaceApplyServiceClient;
import com.itlong.cloud.project.operate.IOperateProjectServiceClient;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.user.app.IAppPadFaceServiceClient;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.DesEncryptUtil;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.random.IdWorker;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <desc>
 * 人脸识别仪控制器。
 * </desc>
 *
 * @createDate 2019-12-16.
 */
@RestController
@RequestMapping("/faceRecognition")
@RefreshScope
public class AppFaceRecognitionController {


    private static final Logger LOG = LoggerFactory.getLogger(AppFaceRecognitionController.class);

    @Value("${" + PlatformConstants.APP_REQUEST_PARAMS_ENCRYPT_KEY + "}")
    public String APP_REQUEST_PARAMS_ENCRYPT_KEY;
    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;
    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;
    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;
    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;
    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;
    @Value("${" + PlatformConstants.H5_PAYMENT_HTML + "}")
    public String H5_PAYMENT_HTML;

    @Autowired
    IAppPadFaceServiceClient iAppPadFaceServiceClient;

    @Autowired
    IPropertyEquipServiceClient equipServiceClient;

    @Autowired
    IOperateProjectServiceClient iOperateProjectServiceClient;

    @Autowired
    IPadFaceSyncDataServiceClient iPadFaceSyncDataServiceClient;

    @Autowired
    IOperateDeviceWhiteListServiceClient iOperateDeviceWhiteListServiceClient;

    @Autowired
    IOperateFaceApplyServiceClient iOperateFaceApplyServiceClient;

    @Autowired
    ICloudIntercomServiceClient iCloudIntercomServiceClient;

    @Autowired
    IAppDeviceServiceClient iAppDeviceServiceClient;
    @Autowired
    IOperateDeviceWhiteListAuthFileConsumeRecordsServiceClient authFileConsumeRecordsServiceClient;
    @Autowired
    IOperateDeviceWhiteListServiceClient deviceWhiteListServiceClient;
    @Autowired
    IOperateDeviceWhiteListAuthRulesServiceClient iOperateDeviceWhiteListAuthRulesServiceClient;
    @Autowired
    IOperateDeviceWhiteListAuthFileServiceClient iOperateDeviceWhiteListAuthFileServiceClient;
    @Autowired
    private IDeviceCloudControllerServiceClient iDeviceCloudControllerServiceClient;

    @Autowired
    private IIotDeviceOnlineServiceClient iIotDeviceOnlineServiceClient;

    @Autowired
    private ICloudElevatorSDKServerCloudServiceClient iCloudElevatorSDKServerCloudServiceClient;

    @Autowired
    private ICloudDeviceBaseServiceClient iCloudDeviceBaseService;

    @Autowired
    RedisService redisService;

    final IdWorker idWorker = new IdWorker(18);

    /**
     * <desc>
     * 设备升级。
     * </desc>
     *
     * @param deviceType   升级包类型；4 维护程序，5 业务程序，6 桌面程序，7 通信程序
     * @param deviceUnique 设备编号
     * @return
     * @author Qiang.S
     * @createDate 2019/12/06
     */
    @RequestMapping(path = "/deviceUpdate", method = RequestMethod.POST)
    @ResponseBody
    public Object deviceUpdate(String deviceUnique, String deviceType, String createTime, String sign, String language) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            deviceUnique = request.getAttribute("deviceUnique") == null ? null : request.getAttribute("deviceUnique").toString();
            deviceType = request.getAttribute("deviceType") == null ? null : request.getAttribute("deviceType").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            //验签
            Map<String, String> params = new HashMap<>();
            params.put("createTime", createTime);
            params.put("language", language);
            params.put("deviceType", deviceType);
            params.put("deviceUnique", deviceUnique);
            //验证签名
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                return new MessageVO(AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode());
            }
            //判断必要信息是否为空
            else if (StringUtils.isBlank(createTime) || StringUtils.isEmpty(deviceUnique)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            List<CloudDeviceUpdateInfoVO> cloudDeviceUpdateInfoVO = iAppPadFaceServiceClient.deviceUpdate(deviceUnique, deviceType);
            List<Map<String, Object>> list = new ArrayList<>();
            if (cloudDeviceUpdateInfoVO != null && cloudDeviceUpdateInfoVO.size() > 0) {
                for (CloudDeviceUpdateInfoVO vo : cloudDeviceUpdateInfoVO) {
                    Map<String, Object> resultMap = new HashMap<>();
                    resultMap.put("fileName", vo.getFileName());
                    resultMap.put("url", vo.getUrl());
                    resultMap.put("md5", vo.getMd5());
                    resultMap.put("versionCode", vo.getVersionCode());
                    resultMap.put("id", vo.getCommandId());
                    resultMap.put("filePackage", vo.getFilePackage());
                    list.add(resultMap);
                }
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), list);
            } else {
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
            }
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_deviceUpdate】设备升级失败", e);
        }
    }

    /**
     * <desc>
     * 设备地址验证
     * </desc>
     *
     * @param sign 签名
     * @param mac  mac地址
     * @return
     * @Author Zhu.yj
     * @createDate 2019/12/13
     */

    @RequestMapping(path = "/checkPadMac", method = RequestMethod.POST)
    @ResponseBody
    public Object checkPadMac(String sign, String mac, String createTime, String language) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            mac = request.getAttribute("mac") == null ? null : request.getAttribute("mac").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            Map<String, String> params = new HashMap<>();
            params.put("mac", mac);
            params.put("language", language);
            params.put("createTime", createTime);
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                return new MessageVO(AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(mac) || StringUtils.isBlank(sign) || StringUtils.isBlank(createTime)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }

            //获取设备白名单信息结果 status,useStatus
            OperateDeviceWhiteListVO operateDeviceWhiteListVO = iOperateDeviceWhiteListServiceClient.getWhiteListByMac(mac);
            //返回空，无此设备
            if (operateDeviceWhiteListVO == null) {
                return new MessageVO(AppErrorCodeEnum.DEVICE_IS_NOT_WHITE_LIST.getErrorCode());
            }
            //status = 2 mac地址被禁用
            if (operateDeviceWhiteListVO.getStatus() == 2) {
                return new MessageVO(AppErrorCodeEnum.DEVICE_IS_FORBIDDEN_IN_WHITE_LIST.getErrorCode());
            }
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("appKey", operateDeviceWhiteListVO.getApiKey());
            resultMap.put("appSecret", operateDeviceWhiteListVO.getApiSecret());
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), resultMap);
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_checkPadMac】设备地址验证失败", e);
        }
    }

    /**
     * <desc>
     * 平板设备信息上报
     * </desc>
     *
     * @param projectId        项目id
     * @param sign
     * @param deviceType       1电梯 2门禁 5群控器
     * @param deviceUnique     平板设备编号
     * @param bindDeviceUnique 平板所绑定的设备编号
     * @return
     * @Author Zhu.yj
     * @createDate 2019/12/13
     */
    @ResponseBody
    @RequestMapping(path = "/reportPadInfo", method = RequestMethod.POST)
    public Object reportPadInfo(String projectId, String sign, String deviceUnique, String deviceType, String bindDeviceUnique, String mac, String createTime, String language) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            deviceUnique = request.getAttribute("deviceUnique") == null ? null : request.getAttribute("deviceUnique").toString();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            deviceType = request.getAttribute("deviceType") == null ? null : request.getAttribute("deviceType").toString();
            bindDeviceUnique = request.getAttribute("bindDeviceUnique") == null ? null : request.getAttribute("bindDeviceUnique").toString();
            mac = request.getAttribute("mac") == null ? null : request.getAttribute("mac").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            Map<String, String> params = new HashMap<>();
            params.put("projectId", projectId);
            params.put("mac", mac);
            params.put("deviceUnique", deviceUnique);
            params.put("bindDeviceUnique", bindDeviceUnique);
            params.put("language", language);
            params.put("createTime", createTime);
            params.put("deviceType", deviceType);
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                return new MessageVO(AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(deviceUnique) || StringUtils.isBlank(projectId) || StringUtils.isBlank(bindDeviceUnique)
                    || StringUtils.isBlank(mac) || StringUtils.isBlank(deviceType)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            //云联动器
            if (deviceType.equals("3")) {
                deviceType = "2";
            }
            //验证项目是否存在
            if (iOperateProjectServiceClient.checkProjectExist(projectId) <= 0) {
                return new MessageVO(AppErrorCodeEnum.PAD_PROJECT_NOT_EXISTS.getErrorCode());
            }
            //绑定的平板设备编号
            String padDeviceUnique = String.format("%s%s%s", projectId, PropertyEquipTypeEnum.PAD.getType(), deviceUnique);
            //绑定的设备编号，由设备机号转换
            StringBuffer bindDeviceUniques = new StringBuffer();
            List<String> bindDeviceUniqueList = StringHandlerUtil.splitStringList(bindDeviceUnique);
            for (String bindDeviceId : bindDeviceUniqueList) {
                String bindDeviceUniqueStr = String.format("%s%s%s", projectId, deviceType, bindDeviceId);
                bindDeviceUniques.append(String.format("%s%s", bindDeviceUniqueStr, ","));
            }
            //去除拼接字符串末尾的逗号
            String bindDeviceUniqueParams = bindDeviceUniques.substring(0, bindDeviceUniques.length() - 1);

            //验证平板所要绑定的设备是否存在
            Integer bindDeviceCount = iAppPadFaceServiceClient.getBindDeviceCount(bindDeviceUniqueParams, deviceType);
            if (bindDeviceCount != bindDeviceUniqueList.size()) {
                return new MessageVO(AppErrorCodeEnum.PAD_BIND_DEVICE_NOT_EXIST_OR_FORBIDDEN.getErrorCode());
            }
            //验证绑定的设备是否是门禁
            if (PropertyEquipTypeEnum.ENTRANCE.getType().toString().equals(deviceType)) {
                //验证绑定设备是否包含普通门禁（此版本暂不支持普通门禁）
                if (iAppPadFaceServiceClient.checkCommonEntranceExist(bindDeviceUniqueParams) > 0
                        && iAppPadFaceServiceClient.checkCommonEntranceExist(bindDeviceUniqueParams) != bindDeviceUniqueList.size()) {
                    return new MessageVO(AppErrorCodeEnum.DEVICE_TYPE_NOT_SUPPORTED.getErrorCode());
                }
            }
            //判断当前项目是否被禁用
            if (iAppPadFaceServiceClient.checkProjectForbidden(projectId) > 0) {
                return new MessageVO(AppErrorCodeEnum.PAD_PROJECT_FORBIDDEN.getErrorCode());
            }
            //判断当前平板设备唯一码的设备是否存在或是否被禁用
            String padStatus = iAppPadFaceServiceClient.getPadDeviceExist(padDeviceUnique);
            if (padStatus == null || "".equals(padStatus)) {
                return new MessageVO(AppErrorCodeEnum.PAD_DEVICE_NOT_EXISTS_STATUS.getErrorCode());
            }
            //设备禁用
            if ("2".equals(padStatus)) {
                return new MessageVO(AppErrorCodeEnum.PAD_DEVICE_FORBIDDEN.getErrorCode());
            }
            //将平板的地址设置为绑定设备的地址
            iAppPadFaceServiceClient.updatePadBridgeInfo(bindDeviceUniqueParams, padDeviceUnique, projectId, mac);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());

        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_reportPadInfo】平板设备信息上报失败", e);
        }
    }

    /**
     * <desc>
     *      上报设备的能力集信息
     * </desc>
     *
     * @return
     * @author pengwei
     * @createDate 2020/11/16
     *
     */
    @RequestMapping(path="/uploadDeviceInfo")
    @ResponseBody
    public Object uploadDeviceInfo(
            String sign,
            String deviceUnique,
            String os,
            String firmware,
            String deviceAttributes,
            String mcu,
            String mac,
            String cmdList,
            String faceLauncher,
            String faceMainTain,
            String faceSerial,
            String facePlugin,
            String hasScreen,
            String touch,
            String size,
            String resolution,
            String cpu,
            String ram,
            String rom,
            String createTime,
            String language
    ){
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            //签名
            sign = getRequestAttributeParam(request,"sign");
            //设备唯一码
            deviceUnique = getRequestAttributeParam(request,"deviceUnique");
            language     = getRequestAttributeParam(request,"language");
            createTime     = getRequestAttributeParam(request,"createTime");
            if (StringUtils.isBlank(deviceUnique)
                    ||deviceUnique.length()<8
                    ||StringUtils.isBlank(sign)
                    ||StringUtils.isBlank(language)
                    ||StringUtils.isBlank(createTime)
                    ) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            //拼装map
            Map<String, String> params =   getRequestAttributeParamMap(request,
                    "deviceUnique","os","firmware",
                    "deviceAttributes","mcu","mac","cmdList",
                    "faceLauncher","faceMainTain",
                    "faceSerial","facePlugin",
                    "hasScreen","touch","size",
                    "resolution","cpu","ram","rom","createTime","language");
            //验签
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                return new MessageVO(AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode());
            }
            //项目id
            String  projectId   =  deviceUnique.substring(0,8);
            //验证项目是否存在
            if (iOperateProjectServiceClient.checkProjectExist(projectId) <= 0) {
                return new MessageVO(AppErrorCodeEnum.PAD_PROJECT_NOT_EXISTS.getErrorCode());
            }
            iAppPadFaceServiceClient.uploadDeviceInfo(params);

            Integer limitDeviceTotal = iCloudDeviceBaseService.getLimitDevicePadTotalBy(deviceUnique);
            //缓存设备最新时间
            redisService.set(RedisConstant.DEVICE_NEW_UPDATE_CACHE_TIME + deviceUnique, System.currentTimeMillis() + "");
            //在线状态保存 超时时间设置五分钟
            if(limitDeviceTotal > 0) {
                redisService.set(RedisConstant.DEVICE_LIMITED_PAD_IS_ONLINE_KEY + deviceUnique,
                        RedisConstant.DEVICE_LIMITED_PAD_IS_ONLINE_CACHE_TIME, "1");
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪】上报设备的能力集信息失败", e);
        }
    }


    /**
     * <desc>
     * 修改同步状态为同步结束
     * </desc>
     *
     * @param syncSerialNo 同步流水号，多个用英文逗号相连
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2019/01/18
     */
    @RequestMapping(path = "/updateSyncStatus", method = RequestMethod.POST)
    @ResponseBody
    public Object updateSyncStatus(String syncSerialNo, String createTime, String sign, String language) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            syncSerialNo = request.getAttribute("syncSerialNo") == null ? null : request.getAttribute("syncSerialNo").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            //验签
            Map<String, String> params = new HashMap<>();
            params.put("syncSerialNo", syncSerialNo);
            params.put("createTime", createTime);
            params.put("language", language);
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                return new MessageVO(AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(syncSerialNo)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            iPadFaceSyncDataServiceClient.updateSyncStatus(syncSerialNo);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_updateSyncStatus】修改同步状态失败", e);
        }
    }

    /**
     * <desc>
     * 通知云端升级失败原因
     * </desc>
     *
     * @param syncSerialNo 同步流水号，多个用英文逗号相连
     * @param msg          失败原因
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2019/01/18
     */
    @RequestMapping(path = "/reportUpdateResult", method = RequestMethod.POST)
    @ResponseBody
    public Object reportUpdateResult(String syncSerialNo, String msg, String createTime, String sign, String language) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            syncSerialNo = request.getAttribute("syncSerialNo") == null ? null : request.getAttribute("syncSerialNo").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            msg = request.getAttribute("msg") == null ? null : request.getAttribute("msg").toString();

            //验签
            Map<String, String> params = new HashMap<>();
            params.put("syncSerialNo", syncSerialNo);
            params.put("msg", msg);
            params.put("createTime", createTime);
            params.put("language", language);
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                return new MessageVO(AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(syncSerialNo)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            iPadFaceSyncDataServiceClient.reportUpdateResult(syncSerialNo, msg);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_reportUpdateResult】通知云端升级失败原因失败", e);
        }
    }

    /**
     * <desc>
     * 平板登陆验证(工程人员)。
     * </desc>
     *
     * @param projectId 项目编号
     * @param userName  帐号
     * @param password  登陆密码
     * @return
     * @author Qiang.S
     * @createDate 2018/05/14
     */
    @RequestMapping(path = "/engineerLoginVerify", method = RequestMethod.POST)
    @ResponseBody
    public Object engineerLoginVerify(String projectId, String userName, String password, String createTime, String sign, String language) {
        MessageVO messageVO;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            userName = request.getAttribute("userName") == null ? null : request.getAttribute("userName").toString();
            password = request.getAttribute("password") == null ? null : request.getAttribute("password").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            //验签
            Map<String, String> params = new HashMap<>();
            params.put("projectId", projectId);
            params.put("userName", userName);
            params.put("password", password);
            params.put("createTime", createTime);
            params.put("language", language);
            //验证签名
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                return new MessageVO(AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode());
            }
            //判断必要信息是否为空
            else if (StringUtils.isBlank(projectId) || StringUtils.isBlank(userName) || StringUtils.isBlank(createTime) || StringUtils.isEmpty(password) || StringUtils.isEmpty(language)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), true);
            //判断帐号是否存在
            int x = iAppPadFaceServiceClient.engineerLoginExistsVerify(userName);
            if (x == 0) {
                messageVO = new MessageVO(AppErrorCodeEnum.PAD_ENGINEER_NOT_EXISTS.getErrorCode());
                return messageVO;
            }

            //判断帐号是否管辖该项目
            int y = iAppPadFaceServiceClient.engineerLoginProjectVerify(projectId, userName);
            if (y == 0) {
                messageVO = new MessageVO(AppErrorCodeEnum.PAD_ENGINEER_VERIFY_PROJECT_FAIL.getErrorCode());
                return messageVO;
            }

            //判断帐号密码是否正确
            int i = iAppPadFaceServiceClient.engineerLoginVerify(projectId, userName, Md5EncryptUtil.md5(password));
            if (i == 0) {
                messageVO = new MessageVO(AppErrorCodeEnum.PAD_ENGINEER_VERIFY_FAIL.getErrorCode());
                return messageVO;
            }
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_engineerLoginVerify】平板登陆验证失败", e);
        }
        return messageVO;
    }

    /**
     * <desc>
     * 获取平板广告(在线离线相结合)。
     * </desc>
     *
     * @param padDeviceUnique 平板deviceUnique
     * @param type            设备类型；1为梯控，2门禁 3云联动器 5为群控器
     * @param projectId       项目编号
     * @param deviceId        设备机号
     * @return
     * @author Qiang.S
     * @createDate 2018/05/14
     */
    @RequestMapping(path = "/getPadFaceAD", method = RequestMethod.POST)
    @ResponseBody
    public Object getPadFaceAD(String padDeviceUnique, String type, String projectId, String deviceId, String createTime, String sign, String language) {
        MessageVO messageVO;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            padDeviceUnique = request.getAttribute("padDeviceUnique") == null ? null : request.getAttribute("padDeviceUnique").toString();
            type = request.getAttribute("type") == null ? null : request.getAttribute("type").toString();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            deviceId = request.getAttribute("deviceId") == null ? null : request.getAttribute("deviceId").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            String deviceUseEnvironment =  request.getAttribute("deviceUseEnvironment") == null ? null : request.getAttribute("deviceUseEnvironment").toString();
            //验签
            Map<String, String> params = new HashMap<>();
            params.put("padDeviceUnique", padDeviceUnique);
            params.put("createTime", createTime);
            params.put("language", language);
            params.put("type", type);
            params.put("projectId", projectId);
            params.put("deviceId", deviceId);
            if(StringUtils.isNotBlank(deviceUseEnvironment)) {
                params.put("deviceUseEnvironment", deviceUseEnvironment);
            }

            //验证签名
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                return new MessageVO(AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode());
            }
            //判断必要信息是否为空
            if (StringUtils.isBlank(padDeviceUnique) || StringUtils.isBlank(type) || StringUtils.isBlank(projectId) || StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(language) || StringUtils.isBlank(createTime)) {
                ErrorCode errorCode = LanguageTypeEnum.CHINESE.getLanguage().equals(language) ? BaseErrorCodeEnum.NOT_PARAM.getErrorCode() : BaseErrorCodeEnumEN.NOT_PARAM.getErrorCode();
                return new MessageVO(errorCode);
            }
            AppPadADKeyVO appPadADKeyVO = new AppPadADKeyVO();
            // 梯控
            List<AppPadADVO> padADVO = new ArrayList<>();
            String isStart = null;
            //获取人脸识别使用key
            OperateFaceApplyInfoVO operateFaceApplyInfoVO = null;
            String deviceUnique = projectId + "4" + padDeviceUnique;
//            DevicePadInfoPO devicePadInfoPO = iAppPadFaceServiceClient.getDevicePadByDeviceUnique(deviceUnique);
            if("2".equals(deviceUseEnvironment)) {
//                if(null == devicePadInfoPO) {
                SpecialDevicePadInfoPO specialDevicePadInfoPO = new SpecialDevicePadInfoPO();
                specialDevicePadInfoPO.setDeviceUnique(deviceUnique);
                specialDevicePadInfoPO.setSpecialDeviceId(idWorker.nextId() + "");
                specialDevicePadInfoPO.setStatus(1);
                specialDevicePadInfoPO.setCreateTime(new Date());
                Integer row = iAppPadFaceServiceClient.save(specialDevicePadInfoPO);

                operateFaceApplyInfoVO = iOperateFaceApplyServiceClient.getFaceByProjectId(projectId);
                if (operateFaceApplyInfoVO != null) {
                    appPadADKeyVO.setAppId(operateFaceApplyInfoVO.getAppId());
                    appPadADKeyVO.setApiKey(operateFaceApplyInfoVO.getApiKey());
                    appPadADKeyVO.setSecretKey(operateFaceApplyInfoVO.getSecretKey());
                    appPadADKeyVO.setFaceScore(operateFaceApplyInfoVO.getFaceScore());
                    appPadADKeyVO.setFaceliveness(operateFaceApplyInfoVO.getFaceliveness());
                }
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_LIMITED_DEVICE_ERROR.getErrorCode(), appPadADKeyVO);
//                }
            }

            //处理云服务费
            List<Map<String, Object>> cloudServiceMapList = iAppPadFaceServiceClient.getDeviceCloudServiceCostEndTime(projectId);
            String projectMinEndTime = iAppDeviceServiceClient.getProjectCloudServiceCostMinEndTime(projectId);
            //云电梯
            if ("1".equals(type)) {
                padADVO = iAppPadFaceServiceClient.getElevatorAD(projectId, deviceId);
                isStart = iAppPadFaceServiceClient.elevatorAuthorityCheck(projectId, deviceId, "12", "1");
                operateFaceApplyInfoVO = iOperateFaceApplyServiceClient.getElevatorFaceByProjectId(projectId);
                for (String deviceIdOne : deviceId.split(",")) {
                    int flag = 0;
                    for (Map<String, Object> cloudServiceMap : cloudServiceMapList) {
                        if (cloudServiceMap.get("deviceUnique") != null &&
                                (projectId + "1" + deviceIdOne).equals(cloudServiceMap.get("deviceUnique").toString())) {
                            //云服务费设备过期时间如果为空,就用项目过期时间
                            appPadADKeyVO.setDeviceEndTime(appPadADKeyVO.getDeviceEndTime() + cloudServiceMap.get("endTime").toString() + ",");
                            flag = 1;
                            break;
                        }
                    }
                    if (flag == 0) {
                        appPadADKeyVO.setDeviceEndTime(appPadADKeyVO.getDeviceEndTime() + (projectMinEndTime == null ? "," : projectMinEndTime + ","));
                    }
                }
            }
            //门禁
            else if ("2".equals(type) || "3".equals(type)) {
                padADVO = iAppPadFaceServiceClient.getEntranceAD(projectId, deviceId);
                isStart = iAppPadFaceServiceClient.entranceAuthorityCheck(projectId, deviceId, "1");
                operateFaceApplyInfoVO = iOperateFaceApplyServiceClient.getFaceByProjectId(projectId);
                for (String deviceIdOne : deviceId.split(",")) {
                    int flag = 0;
                    for (Map<String, Object> cloudServiceMap : cloudServiceMapList) {
                        if (cloudServiceMap.get("deviceUnique") != null &&
                                (projectId + "2" + deviceIdOne).equals(cloudServiceMap.get("deviceUnique").toString())) {
                            //云服务费设备过期时间如果为空,就用项目过期时间
                            appPadADKeyVO.setDeviceEndTime(appPadADKeyVO.getDeviceEndTime() + cloudServiceMap.get("endTime").toString() + ",");
                            flag = 1;
                            break;
                        }
                    }
                    if (flag == 0) {
                        appPadADKeyVO.setDeviceEndTime(appPadADKeyVO.getDeviceEndTime() + (projectMinEndTime == null ? "," : projectMinEndTime + ","));
                    }
                }
            }
            if (appPadADKeyVO.getDeviceEndTime() != null && appPadADKeyVO.getDeviceEndTime().length() >= 1) {
                appPadADKeyVO.setDeviceEndTime(appPadADKeyVO.getDeviceEndTime().substring(0, appPadADKeyVO.getDeviceEndTime().length() - 1));
            }
            //群控器
            else if ("5".equals(type)) {
                PropertyDeviceCloudControllerGetDTO propertyDeviceCloudControllerGetDTO = new PropertyDeviceCloudControllerGetDTO();
                propertyDeviceCloudControllerGetDTO.setProjectId(projectId);
                propertyDeviceCloudControllerGetDTO.setDeviceId(deviceId);
                PropertyDeviceCloudControllerGetVO propertyDeviceCloudControllerGetVO = iDeviceCloudControllerServiceClient.getOne(propertyDeviceCloudControllerGetDTO);
                for (PropertyDeviceCloudControllerEleVO vo : propertyDeviceCloudControllerGetVO.getCloudElevatorList()) {
                    padADVO.addAll(iAppPadFaceServiceClient.getElevatorAD(projectId, vo.getDeviceIdElevator()));//查询群控器控制的电梯广告
                }
                isStart = iAppPadFaceServiceClient.controllerAuthorityCheck(projectId, deviceId);
                operateFaceApplyInfoVO = iOperateFaceApplyServiceClient.getElevatorFaceByProjectId(projectId);
            }
            StringBuffer sb = new StringBuffer();
            if (padADVO != null) {
                padADVO.forEach(padAD -> sb.append(padAD.getAttacheFileUrl() + ","));
            }
            appPadADKeyVO.setPadADVO(sb.toString());
            appPadADKeyVO.setIsStart(isStart == null ? "0" : isStart);
            if (operateFaceApplyInfoVO != null) {
                appPadADKeyVO.setAppId(operateFaceApplyInfoVO.getAppId());
                appPadADKeyVO.setApiKey(operateFaceApplyInfoVO.getApiKey());
                appPadADKeyVO.setSecretKey(operateFaceApplyInfoVO.getSecretKey());
                appPadADKeyVO.setFaceScore(operateFaceApplyInfoVO.getFaceScore());
                appPadADKeyVO.setFaceliveness(operateFaceApplyInfoVO.getFaceliveness());
            }
            OperateProjectDetailVO detailVO = iOperateProjectServiceClient.getDetail(projectId);
            if (detailVO != null) {
                appPadADKeyVO.setOnOffLinePadFace(detailVO.getOnOffLinePadFace());
                appPadADKeyVO.setDataTime(detailVO.getDataTime() == null ? 60 : detailVO.getDataTime());
            }
            //物业增值功能：1开启，0关闭
            ProjectPO oneProject = iOperateProjectServiceClient.getOneProject(projectId);
            if (oneProject == null) {
                LOG.info("try空指针问题追踪projectId" + projectId + "，padDeviceUnique" + padDeviceUnique);
                return new MessageVO(AppErrorCodeEnum.PAD_PROJECT_NOT_EXISTS.getErrorCode());

            } else {
                appPadADKeyVO.setPropertyValueOpen(oneProject.getPropertyValueOpen());
            }
            //获取该设备对应的白名单信息状态
            String padDeviceUniqueStr = String.format("%s%s%s", projectId, PropertyEquipTypeEnum.PAD.getType(), padDeviceUnique);
            Integer whiteListStatus = iOperateDeviceWhiteListServiceClient.getWhiteListStatus(padDeviceUniqueStr);
            //获取项目状态，当项目被禁用时，平板也不可用
            Integer padForbiddenCount = iAppPadFaceServiceClient.checkProjectForbidden(projectId);
            //设备是否禁用的状态
            int forbiddenStatus;
            if (padForbiddenCount == 0) {
                forbiddenStatus = 1;
            } else {
                forbiddenStatus = 2;
            }
            appPadADKeyVO.setWhiteListStatus(forbiddenStatus);
            //取得iot信息
            CloudElevatorVO vo = iAppPadFaceServiceClient.registerPadIot(projectId + "4" + padDeviceUnique);
            if (vo != null) {
                appPadADKeyVO.setIotDeviceSecret(vo.getIotDeviceSecret() == null ? "" : vo.getIotDeviceSecret());
                appPadADKeyVO.setIotProductKey(vo.getIotProductKey() == null ? "" : vo.getIotProductKey());
            } else {
                appPadADKeyVO.setIotDeviceSecret("");
                appPadADKeyVO.setIotProductKey("");
            }
            messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), appPadADKeyVO);
        } catch (Exception e) {
            LOG.info("catch空指针问题追踪projectId" + projectId + "，padDeviceUnique" + padDeviceUnique);
            throw new DataAccessException("【人脸识别仪_getPadFaceAD】获取平板广告失败", e);
        }
        return messageVO;
    }

    /**
     * <desc>
     * 上传通行记录。
     * </desc>
     *
     * @param appUploadPassRecordDTO 设备类型；1为梯控，2门禁
     * @return
     * @author Qiang.S
     * @createDate 2018/05/16
     */
    @RequestMapping(path = "/uploadPassRecord", method = RequestMethod.POST)
    @ResponseBody
    public Object uploadPassRecord(AppUploadPassRecordDTO appUploadPassRecordDTO, String sign) {
        MessageVO messageVO = new MessageVO(BaseErrorCodeEnum.ERROR.getErrorCode(), false);
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            appUploadPassRecordDTO = HttpProtocolUtil.parseRequestParamToDTO(AppUploadPassRecordDTO.class, request);
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            //验签
            Map<String, String> params = new HashMap<>();
            params.put("createTime", appUploadPassRecordDTO.getCreateTime());
            params.put("language", appUploadPassRecordDTO.getLanguage());
            params.put("projectId", appUploadPassRecordDTO.getProjectId());
            params.put("passTime", appUploadPassRecordDTO.getPassTime());
            params.put("uId", appUploadPassRecordDTO.getUId());
            params.put("type", appUploadPassRecordDTO.getType());
            params.put("deviceId", appUploadPassRecordDTO.getDeviceId());
            params.put("imageStr", appUploadPassRecordDTO.getImageStr());
            params.put("imageType", appUploadPassRecordDTO.getImageType());
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                ErrorCode errorCode = LanguageTypeEnum.CHINESE.getLanguage().equals(appUploadPassRecordDTO.getLanguage()) ? AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode() : AppErrorCodeEnumEN.APP_SIGN_ERR.getErrorCode();
                return new MessageVO(errorCode);
            }
            //判断必要信息是否为空
            else if (StringUtils.isBlank(appUploadPassRecordDTO.getImageStr()) || StringUtils.isBlank(appUploadPassRecordDTO.getCreateTime())
                    || StringUtils.isEmpty(appUploadPassRecordDTO.getImageType()) || StringUtils.isEmpty(appUploadPassRecordDTO.getLanguage())
                    || StringUtils.isEmpty(appUploadPassRecordDTO.getPassTime()) || StringUtils.isEmpty(appUploadPassRecordDTO.getType())
                    || StringUtils.isEmpty(appUploadPassRecordDTO.getUId()) || StringUtils.isEmpty(appUploadPassRecordDTO.getDeviceId())) {
                ErrorCode errorCode = LanguageTypeEnum.CHINESE.getLanguage().equals(appUploadPassRecordDTO.getLanguage()) ? BaseErrorCodeEnum.NOT_PARAM.getErrorCode() : BaseErrorCodeEnumEN.NOT_PARAM.getErrorCode();
                return new MessageVO(errorCode);
            }
            if (appUploadPassRecordDTO.getType().equals("3")) {
                appUploadPassRecordDTO.setType("2");
            }
            appUploadPassRecordDTO.setUploadTime(appUploadPassRecordDTO.getCreateTime());
            AppPadDeviceVO appPadDeviceVO = iAppPadFaceServiceClient.getDeviceUnique(appUploadPassRecordDTO.getType(), appUploadPassRecordDTO.getProjectId(),
                    appUploadPassRecordDTO.getDeviceId());
            appUploadPassRecordDTO.setDeviceUnique(appPadDeviceVO.getDeviceUnique());
            appUploadPassRecordDTO.setDeviceName(appPadDeviceVO.getDeviceName());
            String uploadFilePath = uploadImageFile(appUploadPassRecordDTO.getImageStr(), appUploadPassRecordDTO.getImageType(), FileCatalogEnum.FACE_PASS_FILE);
            if (!StringUtils.isBlank(uploadFilePath)) {
                appUploadPassRecordDTO.setUploadFilePath(uploadFilePath);
                iCloudIntercomServiceClient.pushPadFaceRecord(appUploadPassRecordDTO);
                messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), true);
                //若该通行记录为京东项目的，则上报通行记录至京东物联网中台
                if (StringUtils.isNotBlank(appUploadPassRecordDTO.getProjectId())
                        && appUploadPassRecordDTO.getProjectId().equals(redisService.get(PlatformConstants.JD_PROJECT_ID))){
                    SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DATE_FORMAT_TYPE2);
                    String jdUploadUrl = uploadImageFile(appUploadPassRecordDTO.getImageStr(), appUploadPassRecordDTO.getImageType(), FileCatalogEnum.JD_PASS_RECORD_PHOTO_FILE);
                    JDPassRecordDTO jdPassRecordDTO = new JDPassRecordDTO();
                    jdPassRecordDTO.setUserId(appUploadPassRecordDTO.getUId());
                    jdPassRecordDTO.setPassTime(dateFormat.parse(appUploadPassRecordDTO.getPassTime()).getTime());
                    jdPassRecordDTO.setPassType("2");
                    jdPassRecordDTO.setImageStr(jdUploadUrl);
                    jdPassRecordDTO.setImageType(appUploadPassRecordDTO.getImageType());
                    String jdDeviceId = iIotDeviceOnlineServiceClient.getJdDeviceId(appUploadPassRecordDTO.getDeviceUnique(),
                            StringHandlerUtil.getDeviceTypeByDeviceUnique(appUploadPassRecordDTO.getDeviceUnique()));
                    jdPassRecordDTO.setDeviceId(jdDeviceId);
                    iCloudElevatorSDKServerCloudServiceClient.reportPassRecord(jdPassRecordDTO);
                }
            }
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_uploadPassRecord】上传通行记录失败", e);
        }
        return messageVO;
    }

    /**
     * <desc>
     * 平板增量获取变更数据接口
     * </desc>
     *
     * @param deviceId        与平板绑定的deviceUnique
     * @param padDeviceUnique 平板deviceUnique
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2019/01/18
     */
    @RequestMapping(path = "/getIncrementUpdate", method = RequestMethod.POST)
    @ResponseBody
    public Object getIncrementUpdate(String deviceId, String padDeviceUnique, String createTime, String sign, String language) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            deviceId = request.getAttribute("deviceId") == null ? null : request.getAttribute("deviceId").toString();
            padDeviceUnique = request.getAttribute("padDeviceUnique") == null ? null : request.getAttribute("padDeviceUnique").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            String deviceUseEnvironment =  request.getAttribute("deviceUseEnvironment") == null ? null : request.getAttribute("deviceUseEnvironment").toString();
            //验签
            Map<String, String> params = new HashMap<>();
            params.put("createTime", createTime);
            params.put("language", language);
            params.put("deviceId", deviceId);
            params.put("padDeviceUnique", padDeviceUnique);
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                ErrorCode errorCode = LanguageTypeEnum.CHINESE.getLanguage().equals(language) ? AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode() : AppErrorCodeEnumEN.APP_SIGN_ERR.getErrorCode();
                return new MessageVO(errorCode);
            }
            if (StringUtils.isBlank(padDeviceUnique)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            //缓存设备最新时间
            redisService.set(RedisConstant.DEVICE_NEW_UPDATE_CACHE_TIME + padDeviceUnique, System.currentTimeMillis() + "");
            if("2".equals(deviceUseEnvironment)) {
                //在线状态保存 超时时间设置五分钟
                redisService.set(RedisConstant.DEVICE_LIMITED_PAD_IS_ONLINE_KEY + padDeviceUnique,
                        RedisConstant.DEVICE_LIMITED_PAD_IS_ONLINE_CACHE_TIME,"1");
            }

            List<PadIncrementUpdateGetVO> padIncrementUpdateGetVOS = iPadFaceSyncDataServiceClient.getIncrementUpdate(padDeviceUnique);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), padIncrementUpdateGetVOS);
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_getIncrementUpdate】平板增量获取变更数据失败", e);
        }
    }

    /**
     * <desc>
     * 平板获取全量数据
     * </desc>
     *
     * @param createTime
     * @param sign
     * @param language
     * @param deviceId        绑定设备序列号
     * @param padDeviceUnique 平板设备序列号
     * @param bandType        绑定设备类型  1电梯 2门禁 5群控器
     * @return
     * @author Jiaqi.X
     * @createDate 2019/01/23
     */
    @RequestMapping(path = "/pullFull", method = RequestMethod.POST)
    @ResponseBody
    public Object pullFull(String createTime, String sign, String language, String deviceId, String padDeviceUnique, Integer bandType) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            padDeviceUnique = request.getAttribute("padDeviceUnique") == null ? null : request.getAttribute("padDeviceUnique").toString();
            deviceId = request.getAttribute("deviceId") == null ? null : request.getAttribute("deviceId").toString();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            bandType = request.getAttribute("bandType") == null ? null : Integer.parseInt(request.getAttribute("bandType").toString());
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            //验签
            Map<String, String> params = new HashMap<>();
            params.put("createTime", createTime);
            params.put("language", language);
            params.put("deviceId", deviceId);
            params.put("padDeviceUnique", padDeviceUnique);
            params.put("bandType", bandType + "");
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                ErrorCode errorCode = LanguageTypeEnum.CHINESE.getLanguage().equals(language) ? AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode() : AppErrorCodeEnumEN.APP_SIGN_ERR.getErrorCode();
                return new MessageVO(errorCode);
            }
            if (bandType == 3) {
                bandType = 2;
            }
            String projectId = StringHandlerUtil.getProjectIdByDeviceUnique(padDeviceUnique);
            StringBuffer bindDeviceUniques = new StringBuffer();
            List<String> bindDeviceUniqueList = StringHandlerUtil.splitStringList(deviceId);
            for (String bindDeviceId : bindDeviceUniqueList) {
                bindDeviceUniques.append(String.format("%s%s", bindDeviceId, ","));
            }
            //去除拼接字符串末尾的逗号
            String bindDeviceUniqueParams = bindDeviceUniques.substring(0, bindDeviceUniques.length() - 1);
            Map<String, Object> result;
            //验证绑定设备是否普通门禁
            if (iAppPadFaceServiceClient.checkCommonEntranceExist(bindDeviceUniqueParams) > 0) {
                //绑定的普通门禁重写一个逻辑
                result = iAppPadFaceServiceClient.getUserInfoByRoleId(bindDeviceUniqueParams);
            } else {
                List<PropertyDeviceCloudControllerEleVO> cloudElevatorList = new ArrayList<>();
                if (bandType == 5) {//群控器的话查询绑定的云电梯
                    for (String strDeviceId : deviceId.split(",")) {
                        PropertyDeviceCloudControllerGetDTO propertyDeviceCloudControllerGetDTO = new PropertyDeviceCloudControllerGetDTO();
                        propertyDeviceCloudControllerGetDTO.setProjectId(projectId);
                        propertyDeviceCloudControllerGetDTO.setDeviceId(strDeviceId.substring(strDeviceId.length() - 4, strDeviceId.length()));
                        PropertyDeviceCloudControllerGetVO propertyDeviceCloudControllerGetVO = iDeviceCloudControllerServiceClient.getOne(propertyDeviceCloudControllerGetDTO);
                        bandType = 1;//当云电梯使用
                        cloudElevatorList.addAll(propertyDeviceCloudControllerGetVO.getCloudElevatorList());
                        for (PropertyDeviceCloudControllerEleVO vo : cloudElevatorList) {
                            vo.setDeviceUniqueContrroller(strDeviceId);//把绑定的群控器放入vo中后续替换时判断使用
                        }
                    }
                    if (cloudElevatorList.size() > 0) {
                        deviceId = "";//有绑定云电梯就替换,没有就维持不变防止接口报错
                    }
                    for (PropertyDeviceCloudControllerEleVO vo : cloudElevatorList) {
                        deviceId += vo.getDeviceUniqueElevator() + ",";
                    }
                }

                String jdProjectId = redisService.get(PlatformConstants.JD_PROJECT_ID);
                //判断是否京东项目，若是，则走另一套获取全量流程（京东的项目及设备没有地址，需要根据用户的权限去组装全量）
                if (projectId.equals(jdProjectId)){
                    result = iPadFaceSyncDataServiceClient.pullFullNoAddress(deviceId, padDeviceUnique, bandType);
                }else {
                    result = iPadFaceSyncDataServiceClient.pullFull(deviceId, padDeviceUnique, bandType);
                }
                List<Map<String, Object>> users = (List<Map<String, Object>>) result.get("userInfos");
                List<Map<String, Object>> auths = new ArrayList<>();
                if (users != null) {
                    //1获取当前平板设备的所在 地址
                    List<Map> untilMap = iAppDeviceServiceClient.getPadBridgeInfoByDeviceUnique(padDeviceUnique);
                    //去除重复的电梯设备机号
                    Set<String> set = new HashSet<>();
                    for (Map<String, String> map : untilMap) {
                        List<CloudElevatorVO>    DeviceUniques = equipServiceClient.getElevatorListByAddress(untilMap==null?"":map.get("unitId")+"");
                        for (CloudElevatorVO deviceUnique : DeviceUniques) {
                            set.add(deviceUnique.getDeviceUnique());
                        }
                    }



                    for (Map<String, Object> user : users) {
                        if (user.get("houseUserType").toString().equals("5")) {
                            Map<String, Object> auth = new HashMap<String, Object>();
                            if (bandType == 2) {
                                //门禁
                                List<AppDoorDevicesVO> doors = iAppDeviceServiceClient.getDoorDevices(user.get("userId").toString(), StringHandlerUtil.getProjectIdByDeviceUnique(padDeviceUnique), 0);
                                List<Map<String, Object>> sysAuths = new ArrayList<>();
                                auth.put("userId", user.get("userId").toString());
                                auth.put("houseUserType", user.get("houseUserType").toString());
                                auth.put("deviceType", 1);
                                for (AppDoorDevicesVO door : doors) {
                                    Map<String, Object> sysAuth = new HashMap<>();
                                    sysAuth.put("auth", "8");
                                    sysAuth.put("deviceUnique", door.getDeviceUnique());
                                 /*   //1获取当前设备的所在 地址
                                    List<Map> untilMap = iAppDeviceServiceClient.getDeviceEntranceBridgeInfoByDeviceUnique(door.getDeviceUnique());
                                    //
                                    Set<String> set = new HashSet<>();
                                    for (Map<String, String> map : untilMap) {
                                        List<CloudElevatorVO>    DeviceUniques = equipServiceClient.getElevatorListByAddress(untilMap==null?"":map.get("unitId")+"");
                                        for (CloudElevatorVO deviceUnique : DeviceUniques) {
                                            set.add(deviceUnique.getDeviceUnique());
                                        }
                                    }*/

                                    Map commonFloorMap=null;
                                    Map publicFloorMap=null;

                                    if (door.getCommonFloor()!=null){
                                        commonFloorMap = JSON.parseObject(door.getCommonFloor());
                                    }
                                    if (door.getPublicFloor()!=null){
                                        publicFloorMap = JSON.parseObject(door.getPublicFloor());
                                    }
                                    if (set.size()==0){
                                            sysAuth.put("commonFloor","");
                                            sysAuth.put("publicFloor","");
                                    }else {
                                        for (String deviceUnique : set) {
                                            if(commonFloorMap==null){
                                                sysAuth.put("commonFloor","");
                                            }else if (commonFloorMap.containsKey(deviceUnique)) {
                                                sysAuth.put("commonFloor", commonFloorMap == null ? "" : commonFloorMap.get(deviceUnique));
                                            }

                                            if(publicFloorMap==null){
                                                sysAuth.put("publicFloor","");
                                            }else if (publicFloorMap.containsKey(deviceUnique)) {
                                                sysAuth.put("publicFloor", publicFloorMap == null ? "" : publicFloorMap.get(deviceUnique));
                                            }
                                        }
                                    }



                                    sysAuths.add(sysAuth);
                                }
                                auth.put("sysAuths", sysAuths);
                            } else if (bandType == 1) {
                                //电梯
                                List<AppFloorDevicesVO> floors = iAppDeviceServiceClient.getFloorDevices(user.get("userId").toString(), StringHandlerUtil.getProjectIdByDeviceUnique(padDeviceUnique), 0);
                                List<Map<String, Object>> sysAuths = new ArrayList<>();
                                auth.put("userId", user.get("userId").toString());
                                auth.put("houseUserType", user.get("houseUserType").toString());
                                auth.put("deviceType", 2);
                                for (AppFloorDevicesVO floor : floors) {
                                    Map<String, Object> sysAuth = new HashMap<>();
                                    sysAuth.put("auth", floor.getLiveFloor());
//                                    Map commonFloorMap=null;
//                                    Map publicFloorMap=null;
//                                    if (floor.getUserCommonFloor()!=null){
//                                         commonFloorMap = JSON.parseObject(floor.getUserCommonFloor());
//                                    }
//                                    if (floor.getPublicFloor()!=null){
//                                         publicFloorMap = JSON.parseObject(floor.getPublicFloor());
//                                    }
                                    sysAuth.put("deviceUnique", floor.getDeviceUnique());
//                                    sysAuth.put("commonFloor",commonFloorMap!=null && commonFloorMap.containsKey(floor.getDeviceUnique())?commonFloorMap.get(floor.getDeviceUnique()):"");
//                                    sysAuth.put("publicFloor",publicFloorMap!=null && publicFloorMap.containsKey(floor.getDeviceUnique())?publicFloorMap.get(floor.getPublicFloor()):"");
                                    sysAuths.add(sysAuth);
                                }
                                auth.put("sysAuths", sysAuths);
                                if (cloudElevatorList.size() > 0) {
                                    List<Map<String, Object>> newSysAuths = this.getPadAuthForController(cloudElevatorList, sysAuths);
                                    auth.put("sysAuths", newSysAuths);
                                }
                            }
                            auths.add(auth);
                        } else {
                            //访客
                            Map<String, Object> auth = new HashMap<String, Object>();
                            if (bandType == 2) {
                                String entrances[] = user.get("deviceId") != null ? StringHandlerUtil.splitString(user.get("deviceId").toString()) : null;
                                if (entrances != null) {
                                    //门禁
                                    List<Map<String, Object>> sysAuths = new ArrayList<>();
                                    auth.put("userId", user.get("userId").toString());
                                    auth.put("houseUserType", user.get("houseUserType").toString());
                                    auth.put("deviceType", 1);
                                    auth.put("startTime", user.get("startTime"));
                                    auth.put("endTime", user.get("endTime"));
                                    for (String entrance : entrances) {
                                        Map<String, Object> sysAuth = new HashMap<>();
                                        sysAuth.put("auth", "8");
                                        sysAuth.put("deviceUnique", projectId + "2" + entrance);
                                        sysAuths.add(sysAuth);
                                    }
                                    auth.put("sysAuths", sysAuths);
                                }
                            } else if (bandType == 1) {
                                //电梯

                                List<Map<String, Object>> sysAuths = new ArrayList<>();
                                auth.put("userId", user.get("userId").toString());
                                auth.put("houseUserType", user.get("houseUserType").toString());
                                auth.put("deviceType", 2);
                                auth.put("startTime", user.get("startTime"));
                                auth.put("endTime", user.get("endTime"));

                                //若是京东项目（访客无地址），则直接给邀请人的楼层权限
                                if (projectId.equals(jdProjectId)){
                                    List<AppFloorDevicesVO> floors = iAppDeviceServiceClient.getFloorDevices(user.get("userId").toString(), StringHandlerUtil.getProjectIdByDeviceUnique(padDeviceUnique), 0);
                                    for (AppFloorDevicesVO floor : floors) {
                                        Map<String, Object> sysAuth = new HashMap<>();
                                        sysAuth.put("auth", floor.getLiveFloor());
                                        sysAuth.put("deviceUnique", floor.getDeviceUnique());
                                        sysAuths.add(sysAuth);
                                    }
                                }else {
                                    List<Map<String, Object>> elevators = iPadFaceSyncDataServiceClient.getElevatorsByUnitId(user.get("unitId").toString(), user.get("floorNum").toString());
                                    for (Map<String, Object> floor : elevators) {
                                        Map<String, Object> sysAuth = new HashMap<>();
                                        sysAuth.put("auth", floor.get("auth").toString());
                                        sysAuth.put("deviceUnique", floor.get("deviceUnique").toString());
                                        sysAuths.add(sysAuth);
                                    }
                                }
                                auth.put("sysAuths", sysAuths);
                                if (cloudElevatorList.size() > 0) {
                                    List<Map<String, Object>> newSysAuths = this.getPadAuthForController(cloudElevatorList, sysAuths);
                                    auth.put("sysAuths", newSysAuths);
                                }
                            }
                            auths.add(auth);
                        }
                        user.remove("floorNum");
                        user.remove("deviceId");
                        user.remove("unitId");
                    }
                }
                result.put("devices", auths);
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), result);
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_pullFull】平板获取全量数据失败", e);
        }
    }

    /**
     * <desc>
     * 生成人脸指令
     * </desc>
     *
     * @param deviceUnique 人脸识别仪编号
     * @param userInfo     用户信息
     * @return
     * @author Qiang.S
     * @createDate 2019/12/24
     */
    @RequestMapping(path = "/createUserInstruct", method = RequestMethod.POST)
    @ResponseBody
    public Object createUserInstruct(String createTime, String sign, String language, String deviceUnique, String userInfo) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            deviceUnique = request.getAttribute("deviceUnique") == null ? null : request.getAttribute("deviceUnique").toString();
            userInfo = request.getAttribute("userInfo") == null ? null : request.getAttribute("userInfo").toString();
            //验签
            Map<String, String> params = new HashMap<>();
            params.put("createTime", createTime);
            params.put("language", language);
            params.put("deviceUnique", deviceUnique);
            params.put("userInfo", userInfo);
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                ErrorCode errorCode = LanguageTypeEnum.CHINESE.getLanguage().equals(language) ? AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode() : AppErrorCodeEnumEN.APP_SIGN_ERR.getErrorCode();
                return new MessageVO(errorCode);
            }
            if (StringUtils.isBlank(deviceUnique) || StringUtils.isBlank(userInfo)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            iPadFaceSyncDataServiceClient.createUserInstruct(deviceUnique, userInfo,null,0);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_createUserInstruct】生成人脸指令失败", e);
        }
    }

    /**
     * <desc>
     * 用户读取欠费消息
     * </desc>
     *
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2019/05/28
     */
    @RequestMapping(path = "/getArrearageInfo", method = RequestMethod.POST)
    @ResponseBody
    public Object getArrearageInfo(String projectId, String roomId, String deviceUnique, String userId, String type, String deviceType, String deviceId, String createTime, String sign, String language) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            roomId = request.getAttribute("roomId") == null ? null : request.getAttribute("roomId").toString();
            userId = request.getAttribute("userId") == null ? null : request.getAttribute("userId").toString();
            deviceUnique = request.getAttribute("deviceUnique") == null ? null : request.getAttribute("deviceUnique").toString();
            type = request.getAttribute("type") == null ? null : request.getAttribute("type").toString();
            deviceType = request.getAttribute("deviceType") == null ? null : request.getAttribute("deviceType").toString();
            deviceId = request.getAttribute("deviceId") == null ? null : request.getAttribute("deviceId").toString();
            createTime = request.getAttribute("createTime") == null ? null : request.getAttribute("createTime").toString();
            sign = request.getAttribute("sign") == null ? null : request.getAttribute("sign").toString();
            language = request.getAttribute("language") == null ? null : request.getAttribute("language").toString();
            //验签
            Map<String, String> params = new HashMap<>();
            params.put("createTime", createTime);
            params.put("language", language);
            params.put("projectId", projectId);
            params.put("roomId", roomId);
            params.put("userId", userId);
            params.put("type", type);
            params.put("deviceType", deviceType);
            params.put("deviceId", deviceId);
            params.put("deviceUnique", deviceUnique);
            if (!Md5EncryptUtil.checkAppSignValue(params, sign, APP_REQUEST_PARAMS_ENCRYPT_KEY)) {
                ErrorCode errorCode = LanguageTypeEnum.CHINESE.getLanguage().equals(language) ? AppErrorCodeEnum.APP_SIGN_ERR.getErrorCode() : AppErrorCodeEnumEN.APP_SIGN_ERR.getErrorCode();
                return new MessageVO(errorCode);
            }
            if (StringUtils.isBlank(projectId) /*|| StringUtils.isBlank(roomId) || StringUtils.isBlank(userId)*/ || StringUtils.isBlank(type) || StringUtils.isBlank(deviceType)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if (deviceType.equals("3")) {
                deviceType = "2";
            }
            if ("12".equals(deviceType)) {
                deviceType = "1";
            }
            if ("22".equals(deviceType)) {
                deviceType = "2";
            }
            String qrCodeUrl = H5_PAYMENT_HTML + "?projectId=" + projectId + "&userId=" + userId + "&roomId=" + roomId + "&deviceType=" + deviceType + "&deviceId=" + deviceId;

            Map<String, String> data = iAppDeviceServiceClient.getArrearageInfo(projectId, roomId, deviceUnique, userId, type, deviceType);
            if (data != null && !data.isEmpty()) {
                data.put("QRCode", qrCodeUrl);
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), data);
        } catch (Exception e) {
            throw new DataAccessException("【人脸识别仪_getArrearageInfo】用户读取欠费消息失败", e);
        }
    }

    /**
     * <desc>
     * 上传图片文件
     * </desc>
     *
     * @param imageStr  图片二进制
     * @param imageType 图片类型
     * @return
     * @author Qiang.S
     * @createDate 2018-05-07
     */
    private String uploadImageFile(String imageStr, String imageType, FileCatalogEnum fileCatalog) {
        try {
            imageStr = URLDecoder.decode(imageStr, "UTF-8");
        } catch (Exception e) {
            LOG.info("imageStr URLDecoder失败", e);
            return null;
        }
        byte[] bytes = null;
        try {
            bytes = new BASE64Decoder().decodeBuffer(imageStr);
        } catch (IOException e) {
            LOG.info("BASE64Decoder().decodeBuffer失败,imageStr不合法", e);
            return null;
        }
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                byteArrayInputStream,
                imageType,
                FILE_ACCESS_URL,
                fileCatalog.getType()
        );
        try {
            Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
            String returnCode = resultMap.get("returnCode").toString();
            if ("true".equals(returnCode)) {
                String fileUrl = resultMap.get("accessPath").toString();
                return fileUrl;
            } else {
                LOG.info(String.format("图片上传失败，returnCode: %s", returnCode));
                return null;
            }
        } catch (IOException e) {
            LOG.info("UploadFileUtil.uploadFile失败", e);
            return null;
        }
    }

    /**
     * <desc>
     * 处理绑定群控器设备的指令
     * </desc>
     *
     * @param cloudElevatorList
     * @param sysAuths
     * @return
     * @author Qiang.S
     * @createDate 2018-05-07
     */
    private List<Map<String, Object>> getPadAuthForController(List<PropertyDeviceCloudControllerEleVO> cloudElevatorList, List<Map<String, Object>> sysAuths) {
        //判断已遍历过的电梯对应群控机号是否已处理过
        Set<String> deviceUniqueSet = new HashSet<>();
        //替换原sysAuths的新容器
        List<Map<String, Object>> newSysAuths = new ArrayList<>();
        //存电梯对象的新容器
        Map<String, Object> sMap = new HashMap<>();
        //处理绑定了群控器的权限
        for (Map<String, Object> sysMap : sysAuths) {
            //找出当前sysAuth对应的控制器信息
            Optional<PropertyDeviceCloudControllerEleVO> optional = cloudElevatorList.stream().filter(vo -> vo.getDeviceUniqueElevator().equals(sysMap.get("deviceUnique").toString())).findFirst();
            PropertyDeviceCloudControllerEleVO controllerVo = optional.isPresent() ? optional.get() : null;
            if (controllerVo != null) {//有当前群控器管控的云电梯时
                if (deviceUniqueSet.add(controllerVo.getDeviceUniqueContrroller())) {
                    //第一次处理
                    sysMap.put("deviceUnique", controllerVo.getDeviceUniqueContrroller());
                    sMap.put(controllerVo.getDeviceUniqueContrroller(), sysMap);
                } else {
                    Map<String, Object> repeatMap = (HashMap) sMap.get(controllerVo.getDeviceUniqueContrroller());
                    //替换操作 mapAuth  / repeatMap
                    String authAtr = StringHandlerUtil.duplicateEemoval(sysMap.get("auth").toString() + "," + repeatMap.get("auth"));
                    repeatMap.put("auth", authAtr);
                }
            } else {//没有管控的直接无条件添加
                newSysAuths.add(sysMap);
                continue;
            }
        }
        for (String key : sMap.keySet()) {
            newSysAuths.add((HashMap) sMap.get(key));
        }
        return newSysAuths;
    }


    /**
     * <desc>
     * 人脸平板人脸识别仪设备获取白名单授权文件
     * </desc>
     *
     * @Author chengshican
     * @Date 2020-08-12 15:21
     * @Param password 获取白名单授权文件密码   mac 获取对应授权文件的设备的MAC地址
     * @Return
     * @Exception
     */

    @PostMapping("/padFace/getWhiteListAuthFile")
    @ResponseBody
    public Object getWhiteListAuthFile(String password, String mac, HttpServletRequest request) {
        try {
            password = request.getAttribute("password") == null ? null : request.getAttribute("password").toString();
            mac = request.getAttribute("mac") == null ? null : request.getAttribute("mac").toString();
            Date nowTime = new Date();
            if (StringUtils.isBlank(password)) {
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_PASSWORD_IS_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(mac)) {
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_MAC_IS_NULL.getErrorCode());
            }
            //1判断设备mac地址是否在白名单中
            OperateDeviceWhiteListVO whiteListByMac = deviceWhiteListServiceClient.getWhiteListByMac(mac);
            if (whiteListByMac == null) {
                //1.如果白名单里面确实没有这个mac设备，新增白名单记录为设备异常标记为2 ，做新增白名单记录 ，exception_flag为2：异常
                OperateDeviceWhiteListDTO whiteListDTO = new OperateDeviceWhiteListDTO();
                whiteListDTO.setMacAddress(mac);
                whiteListDTO.setExceptionFlag(2);
                whiteListDTO.setChangeFlag(2);
                whiteListDTO.setRequestTimes(1);
                whiteListDTO.setLastUploadTime(nowTime);
                deviceWhiteListServiceClient.save(whiteListDTO);
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_DEVICE_MAC_IS_NULL.getErrorCode());
            }
            if (whiteListByMac != null && "2".equals(whiteListByMac.getChangeFlag())) {
                OperateDeviceWhiteListDTO whiteListDTO = new OperateDeviceWhiteListDTO();
                whiteListDTO.setWhiteListId(whiteListByMac.getWhiteListId());
                whiteListDTO.setRequestTimes(whiteListByMac.getRequestTimes() + 1);
                whiteListDTO.setLastUploadTime(nowTime);
                deviceWhiteListServiceClient.update(whiteListDTO);
                //2.如果白名单里面有这个Mac的记录，但是change_flag为2：未转换
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_DEVICE_MAC_IS_NULL.getErrorCode());
            }
            if (whiteListByMac != null) {
                if ("1".equals(whiteListByMac.getActivateStatus()) && DataStatusEnum.BAN.getType().equals(whiteListByMac.getStatus())) {
                    ErrorCode errorCode = CloudDeviceErrorCodeEnum.CLOUD_MAC_IS_ERROR.getErrorCode();
                    return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_MAC_IS_ERROR.getErrorCode(), String.format(errorCode.getCodeMsg(), mac));
                }
            }
            //获取授权规则信息
            OperateDeviceWhiteListAuthRulesDTO rulesDTO = new OperateDeviceWhiteListAuthRulesDTO();
            rulesDTO.setPassword(Base64.encode(DesEncryptUtil.Encrypt(URLEncoder.encode(new String(password.getBytes()), "utf-8").getBytes(), PlatformConstants.OPERATE_USER_PASSWORD_KEY)));
            //通过输入的授权密码查询授权规则信息  得到 授权文件次数 授权文件的有效时间 授权文件逻辑id
            //2.校验授权文件密码是否输入正确
            List<OperateDeviceWhiteListAuthRulesVO> rules =
                    iOperateDeviceWhiteListAuthRulesServiceClient.getWhiteListAuthRulesByList(rulesDTO);
            if (rules.size() == 0) {
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_PASSWORD_IS_ERROR.getErrorCode());
            }
            String ruleId = null;
            //3.校验获取的设备授权文件的时间
            List<Object> flagList = new ArrayList<>();
            for (OperateDeviceWhiteListAuthRulesVO rule : rules) {
                Date newdate = new Date();//获取激活文件时间
                String beginDateTime = rule.getStartTime();//预先设置好的授权文件有效的开始时间
                String endDateTime = rule.getEndTime();//预先设置好的授权文件有效的结束时间
                boolean flag = DateUtil.getTimeQuantum("yyyy-MM-dd HH:mm:ss", newdate, beginDateTime, endDateTime);
                // 当校验的是获取文件时间在有效期内得到它的规则id，拿出来传给前端，方便后面更新规则表的信息
                // 当校验的是获取文件时间在有效期内并且可用次数和已使用次数不相等，得到它的规则id，拿出来传给前端，方便后面更新规则表的信息
                if (flag && !rule.getAmount().equals(rule.getUsedTimes())) {
                    ruleId = rule.getRuleId();
                }
                flagList.add(flag);
            }
            //判断获取文件的时间是否在授权文件的有效期内
            if (!flagList.contains(true)) {
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_TIME_IS_ERROR.getErrorCode());
            }
            //判断授权文件规则密码次数
            if (ruleId == null) {
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_TIMES_IS_NULL.getErrorCode());
            }
            //4.判断授权文件的剩余次数是否小于等于设置的次数
            OperateDeviceAuthFileDTO deviceAuthFileDTO = new OperateDeviceAuthFileDTO();
            DeviceAuthFileVO effectiveAuthFile = iOperateDeviceWhiteListAuthFileServiceClient.getEffectiveAuthFile(deviceAuthFileDTO);
            if (effectiveAuthFile == null) {
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_FILE_IS_NULL.getErrorCode());
            }

            Map<String, String> data = new HashMap<>();
            data.put("authFileUrl", effectiveAuthFile.getAuthFileUrl());
            data.put("authId", effectiveAuthFile.getAuthId());
            data.put("ruleId", ruleId);
            data.put("consumeFileName", effectiveAuthFile.getFileName());
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), data);

        } catch (Exception e) {
            throw new DataAccessException("【App_getWhiteListAuthFile】用户获取授权文件失败", e);
        }
    }


    /**
     * <desc>
     * 上传设备的激活状态
     * </desc>
     *
     * @Author chengshican
     * @Date 2020-08-12 15:34
     * @Param deviceType 设备类型 1人脸识别云对讲门禁 2人脸识别仪  3一体式人脸识别门禁
     * @Param time 激活时间
     * @Param mac 设备的Mac地址
     * @Param ruleId  授权文件的规则id
     * @Param authId  授权文件的规则id
     * @Return
     * @Exception
     */
    @Transactional
    @UnAuthAccessRequired
    @PostMapping("/padFace/uploadActivateStatus")
    @ResponseBody
    public Object uploadActivateStatus(String deviceType, String time, String mac, String ruleId, String authId, String consumeFileName, HttpServletRequest request) {
        try {
            deviceType = request.getAttribute("deviceType") == null ? null : request.getAttribute("deviceType").toString();
            mac = request.getAttribute("mac") == null ? null : request.getAttribute("mac").toString();
            //activationmMsg = request.getAttribute("activationmMsg") == null ? null : request.getAttribute("activationmMsg").toString();
            ruleId = request.getAttribute("ruleId") == null ? null : request.getAttribute("ruleId").toString();
            authId = request.getAttribute("authId") == null ? null : request.getAttribute("authId").toString();
            time = request.getAttribute("time") == null ? null : request.getAttribute("time").toString();
            consumeFileName = request.getAttribute("consumeFileName") == null ? null : request.getAttribute("consumeFileName").toString();

            if (StringUtils.isBlank(deviceType)) {
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_PASSWORD_IS_NULL.getErrorCode());
            }
            if (StringUtils.isBlank(mac)) {
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_MAC_IS_NULL.getErrorCode());
            }
            //1判断设备mac地址是否在白名单中
            OperateDeviceWhiteListVO whiteListByMac = deviceWhiteListServiceClient.getWhiteListByMac(mac);
            if (whiteListByMac == null) {
                return new MessageVO(CloudDeviceErrorCodeEnum.CLOUD_DEVICE_MAC_IS_NULL.getErrorCode());
            }
            //保存授权文件消息信息表
            OperateDeviceWhiteListAuthFileConsumeRecordsDTO consumeRecordsDTO = new OperateDeviceWhiteListAuthFileConsumeRecordsDTO();
            consumeRecordsDTO.setConsumeNum(1);
            consumeRecordsDTO.setDeviceActivateTime(time);
            consumeRecordsDTO.setDeviceMac(mac);
            consumeRecordsDTO.setConsumeFileName(consumeFileName);
            consumeRecordsDTO.setDeviceType(Integer.parseInt(deviceType));
            consumeRecordsDTO.setAuthId(authId);
            consumeRecordsDTO.setRuleId(ruleId);

            authFileConsumeRecordsServiceClient.save(consumeRecordsDTO);


            //更新白名单设备信息
            OperateDeviceWhiteListDTO operateDeviceWhiteListDTO = new OperateDeviceWhiteListDTO();
            operateDeviceWhiteListDTO.setAuthFileName(consumeFileName);
            operateDeviceWhiteListDTO.setDeviceType(Integer.parseInt(deviceType));
            operateDeviceWhiteListDTO.setMacAddress(mac);
            operateDeviceWhiteListDTO.setActivateTime(time);
            deviceWhiteListServiceClient.updateStatusByAuthIdAndMAC(operateDeviceWhiteListDTO);


            //更新授权文件信息
            OperateDeviceAuthFileDTO operateDeviceAuthFileDTO = new OperateDeviceAuthFileDTO();
            operateDeviceAuthFileDTO.setAuthId(authId);
            operateDeviceAuthFileDTO.setUsedTimes("1");
            operateDeviceAuthFileDTO.setEffectiveTimes("1");
            iOperateDeviceWhiteListAuthFileServiceClient.updateAuthFileByAuthId(operateDeviceAuthFileDTO);


            //更新授权文件规则信息
            OperateDeviceWhiteListAuthRulesDTO authRulesDTO = new OperateDeviceWhiteListAuthRulesDTO();
            authRulesDTO.setRuleId(ruleId);
            authRulesDTO.setUsedTimes(1);
            iOperateDeviceWhiteListAuthRulesServiceClient.updateWhiteListAuthRulesByRuleId(authRulesDTO);


            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());

        } catch (Exception e) {
            throw new DataAccessException("【App_uploadActivateStatus】用户上传设备的激活状态失败", e);
        }
    }

    private String  getRequestAttributeParam(HttpServletRequest request,String param){
        return  request.getAttribute(param) == null
                ? null : request.getAttribute(param).toString();
    }

    private Map<String,String>  getRequestAttributeParamMap(HttpServletRequest request,String... params ){
        Map<String,String>   paramMap  = new HashMap<>();
        if(params!=null){
            for(String  param:params ){
                paramMap.put(param,request.getAttribute(param) == null ? null : request.getAttribute(param).toString());
            }
        }
        return  paramMap;
    }

    @Value("${" + PlatformConstants.ALIBABA_OSS_ENDPOINT + "}")
    public String ALIBABA_OSS_ENDPOINT;
    @Value("${" + PlatformConstants.ALIBABA_OSS_ACCESSID + "}")
    public String ALIBABA_OSS_ACCESSID;
    @Value("${" + PlatformConstants.ALIBABA_OSS_ACCESSKEY + "}")
    public String ALIBABA_OSS_ACCESSKEY;
    @Value("${" + PlatformConstants.ALIBABA_OSS_BUCKET + "}")
    public String ALIBABA_OSS_BUCKET;
    @Value("${" + PlatformConstants.ALIBABA_OSS_DIR + "}")
    public String ALIBABA_OSS_DIR;
    @Value("${" + PlatformConstants.ALIBABA_OSS_MEDIA_DIR + "}")
    public String ALIBABA_OSS_MEDIA_DIR;
    @Value("${" + PlatformConstants.ALIBABA_OSS_CALLBACKURL + "}")
    public String ALIBABA_OSS_CALLBACKURL;

    /**
     * <desc>
     * 设备日志文件上传
     * </desc>
     *
     * @param
     * @return
     * @author caoshuai
     * @createDate 2020/11/12 18:46
     */
    @RequestMapping("/uploadLogFiles")
    public Object uploadLogFiles(MultipartFile[] file, String sn, String deviceType, String deviceUnique) {
        OSS ossClient = null;
        try {
            for (MultipartFile f : file) {

                Map<Object, Object> receiveStatus = new HashMap<>();
//                receiveStatus.put("phase", 2);
//                receiveStatus.put("time", System.currentTimeMillis());
//                receiveStatus.put("size", 0);

                receiveStatus.put("phase", 2);
                receiveStatus.put("createTime", new Date());
                receiveStatus.put("fileName", f.getOriginalFilename());
//                receiveStatus.put("sn", sn);
                receiveStatus.put("deviceType", 5);
                receiveStatus.put("fileSize", f.getSize());
                receiveStatus.put("uploadStatus", 99);
                redisService.set(deviceUnique, 180L, JSON.toJSONString(receiveStatus));
                //保存设备日志文件信息
                DeviceRunLogPO deviceRunLogPO = new DeviceRunLogPO();
                deviceRunLogPO.setFileName(f.getOriginalFilename());
                deviceRunLogPO.setDeviceUnique(deviceUnique);
                deviceRunLogPO.setDeviceType(5);
//                deviceRunLogPO.setSn(sn);
                deviceRunLogPO.setUploadStatus(0);
                deviceRunLogPO.setRunLogId(idWorker.nextId() + "");
                deviceRunLogPO.setCreateTime(new Date());
                deviceRunLogPO.setFileSize(f.getSize());
                iCloudDeviceBaseService.saveDeviceRunLog(deviceRunLogPO);

//                OperateOSSTokenVO ossToken = iIotAliOSSServiceClient.getOSSToken();
//                String host = ALIBABA_OSS_BUCKET + "." + ALIBABA_OSS_ENDPOINT.replace("http://","");
                // Endpoint以杭州为例，其它Region请按实际情况填写。
                String endpoint = ALIBABA_OSS_ENDPOINT;
                // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
                String accessKeyId = ALIBABA_OSS_ACCESSID;
                String accessKeySecret = ALIBABA_OSS_ACCESSKEY;

                // 创建OSSClient实例。
                ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
                // 上传Byte数组。
                PutObjectRequest putObjectRequest = new PutObjectRequest(ALIBABA_OSS_BUCKET, f.getOriginalFilename(),new ByteArrayInputStream(f.getBytes()));
//                PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);

                // 上传回调参数
                Callback callback = new Callback();
                callback.setCallbackUrl(ALIBABA_OSS_CALLBACKURL);
                //（可选）设置回调请求消息头中Host的值，即您的服务器配置Host的值。
                // callback.setCallbackHost("yourCallbackHost");
                // 设置发起回调时请求body的值。
                callback.setCallbackBody("{\\\"sn\\\":${x:sn},\\\"deviceType\\\":${x:deviceType},\\\"deviceUnique\\\":${x:deviceUnique},\\\"fileName\\\":${x:fileName}}");

                // 设置发起回调请求的Content-Type。
                callback.setCalbackBodyType(Callback.CalbackBodyType.JSON);
                callback.addCallbackVar("x:sn", sn);
                callback.addCallbackVar("x:deviceType", deviceType);
                callback.addCallbackVar("x:deviceUnique", deviceRunLogPO.getDeviceUnique());
                callback.addCallbackVar("x:fileName", f.getOriginalFilename());
                putObjectRequest.setCallback(callback);
                PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
                // 读取上传回调返回的消息内容。
                byte[] buffer = new byte[1024];
                int read = putObjectResult.getResponse().getContent().read(buffer);
                LOG.info("上传回调返回的消息内容>>>>>>>>>>>>>>>>>>>>>>>>>>==========================================================" + read);
                // 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
                putObjectResult.getResponse().getContent().close();
            }
        } catch (Exception e) {
            Log.error("【设备日志文件上传】错误：" + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }

        }

        return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
    }
}
